home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
pcboard
/
cbfree13.zip
/
CB.PPS
< prev
next >
Wrap
Text File
|
1996-06-08
|
107KB
|
3,415 lines
;┌───────────────────────────────────────────────────────────────────────────┐
;│ CB.PPE - Written by Dan Shore - SysOp │
;│ The Shoreline BBS │
;│ June, 8, 1996 │
;│ │
;│ Purpose: A PPE Callback program for upgrading users │
;│ │
;│ Do not erase this top part of the source code. │
;├───────────────────────────────────────────────────────────────────────────┤
;│ If you make changes to this source code, add your name to the list and │
;│ the dates of the changes and a quick note of the changes made. │
;│┌───────────────┬──────────────┬──────────────────────────────────────────┐│
;││Name │ Date │ Modifications ││
;│└───────────────┴──────────────┴──────────────────────────────────────────┘│
;│ │
;│ │
;└───────────────────────────────────────────────────────────────────────────┘
;
; In this program there are no functions or procedures, as subroutines
; are used throughout this program. If you want functions and procedures
; or find they will work out better, you have the code at your disposal.
;
; I do not boast about my code, but what I write works, plus I have
; EXTENSIVE comments all throughout the code. This should help you
; follow what is occuring at each place in the program.
;
; If you find a better way to do something in this program or add a new
; feature, share this with the author and others that use the program.
; Posting of changes should be at Salt Air and the author's BBS (FREQ
; the file to the author)
;
; It is the input of yourself and others that will make this PPE the
; best CBV for PCBoard SysOps everywhere.
;
;
; To install in PCBoard:
; ──────────────────────
;
; A. Edit your CMD.LST file(s) to add this:
;
; Charges Per PPE/MNU File Specification -or-
; Command Sec Minute Use Keystroke Substitution
; ══════════════ ═══ ═════════════════ ═════════════════════════════════
; 1) CALLBACK 3 0 0 C:\PCB\PPE\CALLBACK\CB.PPE
;
; Note: You may have to change the pathname to the PPE.
; Note: You may have to change the security level
;
; Note: Another way for the callback to be invoked is have
; the PPE run via an entry in the security specific display
; files. In this display file all you will need is an
; entry that looks like the following:
;
; !C:\PCB\PPE\CALLBACK\CB.PPE
;
; When the security specific file is displayed the
; callback program will be invoked. With this method
; the user is FORCED to use the Callback program. Where
; when it is in the CMD.LST file, the user can execute
; the callback after looking around your BBS first.
;
;
; To setup the PPE:
; ─────────────────
;
; A. Edit the CBCFG.SAM file to match your BBS requirements
; and save your changes to the filename CB.CFG or to a
; node specific configuration file - CBx.CFG. (x = node #)
; ** Remember there are 26 configuration options **
;
; B. Edit the LC-SL.CFG file (Local Call Security File).
; ** One entry for every security level that will use CB.PPE **
;
; C. Edit the LD-SL.CFG file (Long Distance Security File).
; ** One entry for every security level that will use CB.PPE **
;
; D. Edit the BAD-NAME.LST file to include any username(s) you wish to
; be banned from using the callback program.
;
; E. Edit the BAD-NUM.LST file to include any phone numbers you wish
; to be banned from using the callback program.
;
; F. Edit the TRASHCAN.SAM file for blocking areacodes, exhanges or
; the last four numbers from being used in a callback. Rename
; this file to TRASHCAN.DAT
;
; G. OPTIONAL: If you have configuration line #13 set for TRUE, then
; you MUST use the AREACODE.DAT file to check for valid
; areacodes for callback.
;
; H. OPTIONAL: If you have configuation line #14 set for TRUE, then
; you must create a xxxXCHNG.DAT file for EVERY areacode
; that can be a local call to you. (xxx = areacode)
; The format of the file is one EXCHANGE per line.
;
'════════════════════════════════════════════════════════════════════════════
STRING hold ' Generic string variable
STRING hold2 ' Generic string variable
STRING log_entry ' holds information for log file
STRING init_string ' Modem intialization string
STRING phone_number ' Phone number to call
STRING h_phone_number ' Voice Phone number from User record
STRING d_phone_number ' Data Phone number from User record
STRING area_code ' Area code user entered
STRING exchange ' Exchange user entered
STRING last_4_nums ' Last 4 numbers user entered
STRING password_input ' Password user inputs
STRING user_input ' Generic input variable
STRING main_prompt ' Generic prompt variable
STRING modem_string ' Variable to hold strings from modem
STRING send_modem ' Variable to send strings to modem
STRING area_code_local ' Area Codes that are always a local call
STRING local_no_area_code ' Area code that is local
STRING msg_text_file ' Path and filename of msg to import upon
' successful callback
STRING verification_type ' Type of verfication (USER, PASS, or BOTH)
STRING username_input ' Username input for verification
STRING caller_id_info ' Caller ID telephone information
STRING dialing_string ' String to initiate dialing by modem
' ATDT for Touch Tone Dialing
' ATDP for Dial Pulse Dialing
STRING dialing_prefix ' Prefix number added to phone number.
' This is *usually* a number to gain
' access to an outside line.
STRING dialing_suffix ' Suffix number added to phone number.
' This is *usually* a number to gain
' access to an outside line.
STRING suffix_use ' When to use Suffix number
STRING ld_prefix ' Number to add to the beginning of a LD
' callback for NON-INTERNATIONAL.
' An entry of "1" would add a 1 to
' the beginning of the phone number
STRING intl_ld_prefix ' Number to add to the beginning of a LD
' callback for an INTERNATIONAL callback.
' An entry of "011" would add a 011 to
' the eginning of the phone number
STRING post_cbinfo_user_record ' String which determines if we post callback
' information to COMMENT or NOTES in user
' record
STRING country_code ' Country Code - INTL only
STRING exchange_code ' City Code - INTL only
STRING last_nums ' Last numbers - INTL only
STRING cid_string_to_search ' String to search in CID info to find
' the telephone number
STRING add_ac_to_cid ' Areacode to add to beginning of phone
' number when CID only returns 7 digits
' (exchange & last 4)
STRING blocked_cid_string ' If checking for CID blocking, this is
' the string to search for. Examples
' of string are PRIVATE, BLOCKED, etc.
INT us_min_phone_number_length ' Minimum length of callback phone number
' for US calling plan
INT intl_min_phone_number_length ' Minimum length of callback phone number
' for INTL calling plan
INT expired_date_days ' Days to ADD to current expired security
' date (0 = 00/00/00 expired date)
INT expired_level ' Expired Security level for successful
' callback
INT verified_level ' Security level of verified user
INT failure_level ' Security level of user for failed callback
INT highest_sec_level_allowed ' Highest security allowed to use door
INT verification_entry_count ' How many times can password be tried
INT trash_type ' When checking trash can, which field
INT modem_byte ' Modem output read into this variable
' from MGETBYTE
INT duration_to_call ' timeout value
INT local_time_to_call ' Local timeout
INT ld_time_to_call ' LD timeout
INT int_count ' Miscellaneous INT variable
INT count ' Miscellaneous INT variable
INT current_timeout_value ' Show how many seconds have elapsed for
' callback
INT adjust_mins ' Time to add or subtract from users
' current online time
INT ck_length ' Check length of input
INT inp_length ' Allowed length of input
INT cp_required ' Calling plan required by caller
INT start_read ' When to start reading a string
INTEGER start_time ' Timer for starting time
INTEGER end_time ' Timer for ending time
UNSIGNED msg_conf_num ' Conference number to import success
' message
FLOAT cb_remain_number ' Number call back times remaining
FLOAT busy_value ' Value to deduct from total times to
' callback user when a BUSY is encountered
FLOAT no_dial_value ' Value to deduct from total times to
' callback user when a NO DIAL (no dialtone)
' is encountered
FLOAT ring_value ' Value to deduct from total times to
' callback user when a RING (incoming call)
' is encountered
REAL temp_real ' Generic REAL variable
TIME local_start_time ' Start time to allow local callbacks
TIME local_end_time ' End time to allow local callbacks
TIME ld_start_time ' Start time to allow LD callbacks
TIME ld_end_time ' End time to allow LD callbacks
BOOLEAN made_connection ' Flag for made callback connection
BOOLEAN found1 ' Flag when searching area code/exchange
' files
BOOLEAN local_call ' Local or LD Call Flag
BOOLEAN already_verified ' User has been verified before
BOOLEAN no_call ' Callback is outside allowed time if true
' and no callback will be made
BOOLEAN user_record_phone ' Flag file to indicate if user used
' phone number from user record info
BOOLEAN do_increase ' Flag to determine if user gets security
' level increase
BOOLEAN sysop_recycle ' Flag for when SysOp hits space bar to
' recycle callback
BOOLEAN password_correct ' Flag for when password verification is
' correct
BOOLEAN username_correct ' Flag for when username verification is
' correct
BOOLEAN use_other ' Flag to display "Use Other Phone Number"
BOOLEAN ck_area_code ' Flag to use AREACODE.DAT file to check for
' allowed area codes
BOOLEAN ck_exchange ' Flag to look for xxxXCHNG.DAT file for
' determining LOCAL CALLS
BOOLEAN up_already_verified ' Flag to upgrade a previously verified user
BOOLEAN process_caller_id ' Flag to turn on CALLER ID processing
BOOLEAN use_caller_id_info ' Flag to use caller ID information
BOOLEAN upgrade_caller_id ' Flag to upgrade user if caller ID matches
' phone number(s) from user record
BOOLEAN us_call_plan ' Flag to indicate US calling plan type
BOOLEAN intl_call_plan ' Flag to indicate INTL calling plan type
BOOLEAN intl_callback ' True if callback is international
BOOLEAN cid_matches_user ' Flag for CID matching user record phone #
BOOLEAN drop_ld_cb ' Flag to hangup (TRUE) after a LD Callback
BOOLEAN prompt_for_zero ' Flag to prompt the user to add a "0" to #
BOOLEAN cid_use_hex ' Phone number is in HEX and not ASCII
BOOLEAN improper_user_rec_phone ' Flag for user record phone number chosen
' in proper format
BOOLEAN block_ld_callbacks ' Flag to block ALL Long Disntance callbacks
BOOLEAN stop_blocked_cid_caller ' Flag to stop callback if user is blocking
' CID information (will appear as PRIVATE)
'
'═════════════════════════════════════════════════════════════════════════════
'
:MAIN
'
' Write to PCB Callers File that user entered Callback
'
LOG "*** User Entered Callback Program ***", FALSE
'
' Callback is ALWAYS local unless overriden (User entered a LD #)
'
local_call = TRUE
'
' Open our NODE Specific Log file in append mode
'
FAPPEND 7, PPEPATH()+"NODE" + STRING(PCBNODE()) + ".LOG", O_WR, S_DW
FPUTLN 7, ""
FPUTLN 7, "*********** Starting up CallBack ************"
'
' Read the programs configuration file (CB?.CFG -or- CB.CFG)
'
GOSUB READ_CFG
'
' Get current user info and log it
'
GETUSER
FPUTLN 7, "Callback started for user: ", U_NAME()
FPUTLN 7, " Date: ", DATE()
FPUTLN 7, " Time: ", TIME()
FPUTLN 7, " User's Security Level: ", U_SEC
FPUTLN 7, " User's Expiration Date: ", U_EXPDATE
FPUT 7, " Verification Using: "
IF (verification_type = "BOTH") THEN FPUTLN 7, "Username & Password Check"
ELSE IF (verification_type = "USER") THEN FPUTLN 7, "Username Check"
ELSE IF (verification_type = "PASS") THEN FPUTLN 7, "Password Check"
END IF
'
' Check to see if their security level is too high to use the program
'
GOSUB SECURITY_CHECK
'
' Check to see if the username is in the BAD-NAME.LST file
'
GOSUB BAD_NAMES
'
' Clear the screen and welcome the user to the Callback Program
'
CLS
DISPFILE PPEPATH() + "WELCOME", GRAPH+LANG
'
' Prompt user to C)ontinue callback or E)xit back to BBS
'
main_prompt = " @X0EC@X0F)@X02ontinue Callback process, @X0EE@X0F)@X02xit Callback@X0F"
user_input = "C"
INPUTSTR main_prompt, user_input, @X0F, 1,"CE", FIELDLEN+GUIDE+LFAFTER+UPCASE
'
' See if user choose to exit the PPE
'
IF (user_input = "E") THEN
FPUTLN 7, "**-->> User aborted callback"
local_call = TRUE
GOTO EXIT_PROG
END IF
'
' US and INTL (BOTH) enabled, ask user which format to use
'
IF (us_call_plan && intl_call_plan) THEN
'
' Display file so user can choose callback phone format
'
' Default = US Format (ac/ex/4)
'
DISPFILE PPEPATH() + "PFORM1", GRAPH+LANG+SEC
user_input = "1"
NEWLINE
main_prompt = " @X0EPlease make your selection"
INPUTSTR main_prompt, user_input, @X0F, 1, "12", FIELDLEN+GUIDE+LFAFTER
'
' See what the user selected
'
IF (user_input = "1") THEN
cp_required = 1
FPUTLN 7, " Calling format selected: US"
ELSE
cp_required = 2
FPUTLN 7, " Calling format selected: INTL"
END IF
'
' Display file so user can tell us if International Callback or not
'
' Default = Non-International Callback (Local or Long Distance)
'
DISPFILE PPEPATH() + "PFORM2", GRAPH+LANG+SEC
user_input = "1"
NEWLINE
main_prompt = " @X0EPlease make your selection"
INPUTSTR main_prompt, user_input, @X0F, 1, "12", FIELDLEN+GUIDE+LFAFTER
'
' Get users response
'
IF (user_input = 2) THEN
FPUTLN 7, " International Call: TRUE"
intl_callback = TRUE
ELSE
FPUTLN 7, " International Call: FALSE"
END IF
'
' Only use US call plan (ac/ex/4)
'
ELSE IF (us_call_plan) THEN
cp_required = 1
'
' Only use INTL call plan (cc/cc/last)
'
ELSE IF (intl_call_plan) THEN
cp_required = 2
END IF
'
' We will now get the users phone number they want to use
' for callback. If CID is used, we will use that number
' and not prompt the user for a phone number.
'
GOSUB BEGIN_CALLBACK
'
' Check the BAD_NUM.LST file for a matching phone number
'
IF (EXIST(PPEPATH() + "BAD-NUM.LST")) GOSUB CHECK_BAD_NUMBER
'
' See if the callback will be local or LD and
' check the times allowed to call
'
GOSUB CK_ALLOWED_TIMES
'
' Open the proper security file for local or long distance callers
'
GOSUB READ_SECURITY_FILE
'
' Set variable to false for use later on in the program
'
found1 = FALSE
'
' Search VERIFIED.LOG for verified phone numbers
'
GOSUB CK_VERIFIED_LOG
'
' Check Flag file (do_increase) for TRUE
' If TRUE (User has been verified before..Do not re-verify)
'
IF (do_increase) THEN
GOSUB INCREASE_LEVEL
GOTO EXIT_PROG
END IF
'
' IF processing CALLER ID and caller ID information is not
' blank - Check to see if number matches phone numbers
' from user record.
'
IF (process_caller_id && caller_id_info != "") THEN
'
' If configuration is set to automatically upgrade the
' user if the caller ID matches user record phone number(s)
' then process the following code.
'
IF (upgrade_caller_id) THEN
'
' Write CID to log file
'
FPUT 7, " Caller ID = User Record: "
'
' See if we match the user record phone number with Caller ID.
' If so, and the sysop has set upgrades to be done when the caller
' ID matches a user record phone number, upgrade the user and exit
' the callback program
'
IF (caller_id_info = h_phone_number || caller_id_info = d_phone_number) THEN
'
' Set flag to true for matching user record with CID
' and write to log file
'
cid_matches_user = TRUE
FPUTLN 7, "PHONE NUMBER MATCHES USER RECORD"
'
' Set variables to equal verification information
'
password_input = U_PWD
username_input = U_NAME()
'
' Set variable so security level increase is done
'
do_increase = TRUE
'
' set flag to local call so user does not get
' disconnected when CID matches user record
' and it is a long distance phone call
'
local_call = TRUE
'
' Increase their security level for a successful callback
'
GOSUB INCREASE_LEVEL
'
' Time to say byby....
'
GOTO EXIT_PROG
'
ELSE
'
' Caller ID number DOES NOT match number(s) in User Record.
' Callback will be done using the CALLER ID phone Number,
'
' Log this information in the callback log file and the
' callers log
'
FPUTLN 7, "FALSE"
FPUTLN 7, "**-->> Caller ID did NOT match User Record entries"
FPUTLN 7, " User's Security Level: ", U_SEC
LOG "**-->> Caller ID did NOT match User Record entries", FALSE
'
END IF
END IF ' upgrade_caller_id
END IF ' process _caller_id
'
' Ok, we are ready to call out now
' Show the user instructions on how to answer phone
'
CLS
DISPFILE PPEPATH() + "INST", GRAPH+LANG+SEC
'
' Ask the user to continue or exit back to BBS - Last Chance!
'
hold = "P"
main_prompt = "@X0EP@X0F)@X02roceed with callback, or @X0EE@X0F)@X02xit back to BBS"
INPUTSTR main_prompt, hold, @X0F, 1, "EP", FIELDLEN+GUIDE+LFAFTER+UPCASE
'
' Check users response
'
IF (hold != "P") THEN
FPUTLN 7, "**-->> User aborted callback"
local_call = TRUE
GOTO EXIT_PROG
END IF
'
' Remind user how to answer incoming call before disconnecting
'
CLS
PRINTLN "@X0ARemember, type @X0A@X0FATA @X0Athen hit the @X0FENTER @X0Akey after your phone rings@X0F....@X07"
PRINTLN
'
' Set timeout duration from configuration file according to
' local or LD call and build number for modem to dial
'
GOSUB SET_DURATION_BUILD_MODEM_DIAL
'
' IF not on local, write LOG file, and make phone call
'
IF (!ONLOCAL()) THEN
'
' Close log file and reopen to commit prior logged information to disk
'
FCLOSE 7
FAPPEND 7,PPEPATH()+"NODE" + STRING(PCBNODE()) + ".LOG",O_WR,S_DW
'
' Perform callback - Continue till timeout or connect
'
GOSUB PERFORM_CALL
'
ELSE
'
' Log we are in LOCAL mode, but show what modem
' dial string would have been
'
FPUTLN 7, " Local Test-Modem Command: ", send_modem
'
END IF
'
' Got a connect from user, or this is a LOCAL user.
' Time to get their password for verification
'
IF (made_connection || ONLOCAL()) THEN
'
' IF not on local, write to log, turn on CD and KBD Checking
'
IF (!ONLOCAL()) THEN
FPUTLN 7, " Modem results: We are CONNECTED!!!..."
COLOR @X0E
ANSIPOS 2,18
SPRINT "Waiting for line to settle down..."
ANSIPOS 2,18
COLOR @X07
DELAY 54
CDCHKON
KBDCHKON
ELSE
NEWLINE
PRINTLN " @X0F*** @X0CThis is a Local Logon Callback @X0F- @X0ENo Phone call made @X0F***@X07"
NEWLINE
DELAY 36
END IF
'
' Ask the user for their Password and verify it
'
GOSUB ASK_VERIFY_VERIFICATION_INFO
'
' User *has* entered correct password, or else they would not have
' gotten to this part of the code, so tell'm whats up by displaying
' the verification file.
'
' Add their phone number to verified file, raise their security
' level and add days (set in .CFG file) to their date of expiration
'
GOSUB INCREASE_LEVEL
'
ELSE
'
' Too many tries attempted to call user for callback
'
FPUTLN 7, "**-->> Too many tries exceeded to make callback"
'
' Update users security to "FAILED" security level
'
U_SEC = failure_level
FPUTLN 7, " Security Level set to: " + STRING(failure_level)
PUTUSER
'
' Clear the screen of the "CALLB" display
'
CLS
'
END IF
'
' Time to exit the PPE
'
GOTO EXIT_PROG
:END_MAIN
'┌─────────────────────────────────────────────────────────────────────────┐
'│ │
'│ START OF SUBROUTINES USED IN CB.PPE │
'│ │
'└─────────────────────────────────────────────────────────────────────────┘
'
' Add voice number from User Record to VERIFIED.LOG
'
:ADD_VOICE_TO_LOG
'
' Add Voice phone number to Verified.Log
'
' Entry that begins with an "*" is International
'
IF (cp_required = 1) THEN
h_phone_number = MID(h_phone_number, 1, 3) + "-" + MID(h_phone_number, 4, 3) + "-" +MID(h_phone_number, 7, 4)
ELSE IF (cp_required = 2) THEN
hold = "*" + MID(h_phone_number, 1, LEN(country_code)) + "-" \
+ MID(h_phone_number, LEN(country_code)+1, LEN(exchange_code)) + "-" \
+ MID(h_phone_number, LEN(country_code) + LEN(exchange_code) + 1, LEN(h_phone_number) - LEN(country_code) + LEN(exchange_code))
hold = TRIM(hold, " ")
h_phone_number = hold + SPACE(24-LEN(hold))
END IF
hold = h_phone_number + " " + U_NAME() + " " + STRING(TIME()) + " " + STRING(DATE()) + " " + "H/V from User Record"
FPUTLN 1, hold
RETURN
'
' Add data number from User Record to VERIFIED.LOG
'
:ADD_DATA_TO_LOG
'
' Add Data phone number to Verified.Log
'
' Entry that begins with an "*" is International
'
IF (cp_required = 1) THEN
d_phone_number = MID(d_phone_number, 1, 3) + "-" + MID(d_phone_number, 4, 3) + "-" + MID(d_phone_number, 7, 4)
ELSE IF (cp_required = 2) THEN
hold = "*" + MID(d_phone_number, 1, LEN(country_code)) + "-" \
+ MID(d_phone_number, LEN(country_code)+1, LEN(exchange_code)) + "-" \
+ MID(d_phone_number, LEN(country_code) + LEN(exchange_code) + 1, LEN(d_phone_number) - LEN(country_code) + LEN(exchange_code))
hold = TRIM(hold, " ")
d_phone_number = hold + SPACE(24-LEN(hold))
END IF
hold = d_phone_number + " " + U_NAME() + " " + STRING(TIME()) + " " + STRING(DATE()) + " " + "Data from User Record"
FPUTLN 1, hold
RETURN
'
' Clean up telephone numbers from user record
'
:CLEAN_UP_NUMBER
'
' Strip characters
'
hold = STRIPSTR(hold,"+")
hold = STRIPSTR(hold,"-")
hold = STRIPSTR(hold,")")
hold = STRIPSTR(hold,"(")
hold = STRIPSTR(hold," ")
RETURN
'
' Check area code entered by user
'
:CHECK_AREA_CODE
'
' Open file and read entries. If a match if found,
' FOUND1 is set to TRUE
'
IF (cp_required = 1) THEN
FOPEN 1, PPEPATH() + "AREACODE.DAT", O_RD, S_DN
ELSE IF (cp_required = 2) THEN
FOPEN 1, PPEPATH() + "CNTYCODE.DAT", O_RD, S_DN
END IF
'
' Read through file until a match is found
'
WHILE (!found1) DO
FGET 1,hold
IF (FERR(1)) BREAK
IF (cp_required = 1) THEN
IF (MID(hold,1,3) = area_code) found1 = TRUE
IF (MID(hold,1,3) > area_code) BREAK
ELSE IF (cp_required = 2) THEN
IF (MID(hold,1,3) = country_code) found1 = TRUE
END IF
END WHILE
FCLOSE 1
RETURN
'
' Check exchange entered by user
'
:CHECK_EXCHANGE
'
' See if EXCHANGE FILE exists to test for a local phone call
'
hold = PPEPATH() + area_code + "XCHNG.DAT"
'
' No exchange file found
'
IF (!EXIST(hold)) THEN
FPUTLN 7, " No Exchange File : ", hold
RETURN
END IF
'
' Log activity
'
FPUTLN 7, " Searching Exchange File: ", area_code + "XCHNG.DAT"
'
' Open file and if a match if found FOUND1 is set to TRUE
'
FOPEN 1, hold, O_RD, S_DN
WHILE (!found1) DO
FGET 1,hold
IF (FERR(1)) BREAK
IF (MID(hold,1,3) = exchange) found1 = TRUE
END WHILE
FCLOSE 1
RETURN
'
' Common exit point for program
'
:EXIT_PROG
'
' If not a local call, or user is NOT exiting the PPE,
' hangup the modem. (Disconnect user)
'
IF (!local_call) THEN
IF (ONLOCAL()) THEN
PRINTLN "Local Testing - User stays online"
FPUTLN 7, "Local Testing - User stays online"
GOSUB CLOSE_LOG
ELSE
GOSUB CLOSE_LOG
HANGUP
END IF
ELSE
GOSUB CLOSE_LOG
END IF
LOG "*** User Exited Callback Program ***", FALSE
DEFCOLOR
'
' If we did not make a connection, turn on carrier detect checking
' and keyboard timeout checking before exiting the PPE.
'
' This is *BETA* code here to try to solve a OS/2 problem.
'
IF (!made_connection && !ONLOCAL()) THEN
CDCHKON
KBDCHKON
END IF
END
'
'
'
:CLOSE_LOG
'
' Final logging and close log file
'
FPUTLN 7, " User's Expiration Date: ", U_EXPDATE
FPUTLN 7, "@@@@@@@@@@@ Ending CallBack @@@@@@@@@@@@"
FCLOSE 7
RETURN
'
' Search trashcan file for sections of callback numbers
' that are not allowed
'
:TRASH_CAN
'
' See if the TRASHCAN.DAT file exists...If not exit the subroutine
'
IF (!EXIST(PPEPATH() + "TRASHCAN.DAT")) RETURN
'
' Open trashcan file
'
FOPEN 1, PPEPATH() + "TRASHCAN.DAT", O_RD, S_DN
'
' Get line by line from trashcan file and read 1st 12 characters
'
WHILE (1) DO
FGET 1,hold
IF (FERR(1)) BREAK
'
' See if the line is a comment
'
IF (LEFT(hold,1) = "'") CONTINUE
'
' If using US calling plan and the entry is International read
' the next line
'
IF (LEFT(hold,1) = "*" && cp_required = 1) CONTINUE
'
' Retrieve the trashcan info from the line
'
IF (cp_required = 1) THEN
hold = MID(hold,1,25)
ELSE IF (cp_required = 2) THEN
hold = MID(hold, 2, 24)
END IF
'
' Check for trash_type (area code = 1, exchange = 2, last 4 = 3)
' (country code = 4, city code = 5, last nums = 6)
SELECT CASE (trash_type)
CASE 1
'
' Check for area codes not allowed, if found exit PPE.
'
IF (MID(hold,1,3) = area_code) THEN
PRINTLN
PRINTLN " @X0F*** @X0CThe Area Code "+ area_code +" is @X0Fnot allowed @X0Cfor callback@X07"
NEWLINE
FPUTLN 7, "**-->> Area Code matches entry in Trashcan"
DELAY 54
GOTO EXIT_PROG
END IF
CASE 2
'
' Check for exchange's not allowed, if found exit PPE
'
IF (MID(hold,5,3) = exchange) THEN
PRINTLN
PRINTLN " @X0F*** @X0CThe exchange " + exchange +" is @X0Fnot allowed @X0Cfor callback@X07"
NEWLINE
FPUTLN 7, "**-->> Exchange matches entry in Trashcan"
DELAY 54
GOTO EXIT_PROG
END IF
CASE 3
'
' Check for last_4_nums's not allowed, if found exit the PPE.
'
IF (MID(hold,9,4) = last_4_nums) THEN
PRINTLN
PRINTLN " @X0F*** @X0CThe last 4 number " + last_4_nums + " are @X0Fnot allowed @X0Cfor callback@X07"
NEWLINE
FPUTLN 7, "**-->> Last 4 Numbers matches entry in Trashcan"
DELAY 54
GOTO EXIT_PROG
END IF
CASE 4
'
' Check for Country Codes not allowed, if found exit PPE
'
IF (RTRIM(MID(hold,1,3)," ") = country_code) THEN
PRINTLN
PRINTLN " @X0F*** @X0CThe country code " + country_code +" is @X0Fnot allowed @X0Cfor callback@X07"
NEWLINE
FPUTLN 7, "**-->> Exchange matches entry in Trashcan"
DELAY 54
GOTO EXIT_PROG
END IF
CASE 5
'
' Check for City Codes not allowed, if found exit PPE
'
IF (RTRIM(MID(hold,5,4)," ") = exchange_code) THEN
PRINTLN
PRINTLN " @X0F*** @X0CThe city code " + exchange_code +" is @X0Fnot allowed @X0Cfor callback@X07"
NEWLINE
FPUTLN 7, "**-->> Exchange matches entry in Trashcan"
DELAY 54
GOTO EXIT_PROG
END IF
CASE 6
'
' Check for last numbers not allowed, if found exit PPE
'
IF (RTRIM(MID(hold,10,8)," ") = last_nums) THEN
PRINTLN
PRINTLN " @X0F*** @X0CThe last numbers " + last_nums +" are @X0Fnot allowed @X0Cfor callback@X07"
NEWLINE
FPUTLN 7, "**-->> Exchange matches entry in Trashcan"
DELAY 54
GOTO EXIT_PROG
END IF
END SELECT
END WHILE
FCLOSE 1
RETURN
'
' Read CB.CFG - Configuration file
'
:READ_CFG
'
'
'
NEWLINE
PRINTLN "@X03Reading configuration.....@X07"
'
' Check for node specific .CFG file. If not found use CB.CFG
'
IF (EXIST(PPEPATH() + "CB" + STRING(PCBNODE()) + ".CFG")) THEN
FPUTLN 7, " Using configuration file: ", "CB" + STRING(PCBNODE()) + ".CFG"
FOPEN 1, PPEPATH() + "CB" + STRING(PCBNODE()) + ".CFG", O_RD, S_DN
ELSE
FOPEN 1, PPEPATH() + "CB.CFG", O_RD, S_DN
IF (FERR(1)) THEN
NEWLINE
PRINTLN "Configuration file (CB.CFG) NOT FOUND!!....Program Aborting"
NEWLINE
FPUTLN 7, "**-->> Configuration File Not Found!!!! - CB.CFG - Program Aborted"
WAIT
GOTO EXIT_PROG
END IF
FPUTLN 7, " Using configuration file: CB.CFG"
END IF
'
' Initialize line counter
'
count = 1
WHILE (1) DO
'
' Check how many lines we have read from .CFG file
'
IF (count > 26) BREAK
FGET 1, hold
hold = TRIM(hold," ")
'
' Make sure we have read AT LEAST 26 Lines or else the .CFG file is wrong
'
IF (FERR(1) && count < 26) THEN
FPUTLN 7, "##### CONFIGURATION FILE DOES NOT CONTAIN 26 ENTRIES #####"
GOTO EXIT_PROG
END IF
'
' See if the line is a comment
'
IF (LEFT(hold,1) = "#" || LEFT(hold,1) = "'") CONTINUE
'
' Process the line we just read (count)
'
SELECT CASE (count)
CASE 1
highest_sec_level_allowed = TOINT(hold)
CASE 2
TOKENIZE hold
verification_type = UPPER(GETTOKEN())
verification_entry_count = TOINT(GETTOKEN())
CASE 3
cb_remain_number = TOFLOAT(hold)
CASE 4
init_string = UPPER(hold)
CASE 5
local_time_to_call = TOINT(hold)
CASE 6
ld_time_to_call = TOINT(hold)
CASE 7
area_code_local = hold
CASE 8
local_no_area_code = hold
CASE 9
TOKENIZE hold
local_start_time = GETTOKEN()
local_end_time = GETTOKEN()
CASE 10
TOKENIZE hold
IF (!INSTR(hold, "DISABLED")) THEN
ld_start_time = GETTOKEN()
ld_end_time = GETTOKEN()
ELSE
block_ld_callbacks = TRUE
END IF
CASE 11
IF (hold != "") THEN
TOKENIZE hold
msg_conf_num = TOLONG(GETTOKEN())
msg_text_file = GETTOKEN()
END IF
CASE 12
IF (UPPER(hold) = "TRUE") use_other = TRUE
CASE 13
IF (UPPER(hold) = "TRUE") ck_area_code = TRUE
CASE 14
IF (UPPER(hold) = "TRUE") ck_exchange = TRUE
CASE 15
IF (UPPER(hold) = "TRUE") up_already_verified = TRUE
CASE 16
busy_value = TOFLOAT(hold)
CASE 17
no_dial_value = TOFLOAT(hold)
CASE 18
ring_value = TOFLOAT(hold)
CASE 19
hold = REPLACESTR (hold," ","_")
TOKENIZE hold
hold2 = UPPER(GETTOKEN())
IF (hold2 = "TRUE") THEN
process_caller_id = TRUE
hold2 = UPPER(GETTOKEN())
IF (hold2 = "TRUE") upgrade_caller_id = TRUE
cid_string_to_search = UPPER(GETTOKEN())
cid_string_to_search = REPLACESTR(cid_string_to_search,"_"," ")
add_ac_to_cid = GETTOKEN()
hold2 = UPPER(GETTOKEN())
IF (hold2 = "H") cid_use_hex = TRUE
hold2 = UPPER(GETTOKEN())
IF (hold2 = "TRUE") THEN
stop_blocked_cid_caller = TRUE
blocked_cid_string = UPPER(GETTOKEN())
END IF
END IF
CASE 20
dialing_string = hold
CASE 21
TOKENIZE hold
dialing_prefix = GETTOKEN()
dialing_suffix = GETTOKEN()
'
' Suffix Use Codes
'
' "A" - all the time, "D" - LD only, "L" - local only
'
suffix_use = UPPER(GETTOKEN())
CASE 22
TOKENIZE hold
ld_prefix = GETTOKEN()
intl_ld_prefix = GETTOKEN()
CASE 23
post_cbinfo_user_record = UPPER(hold)
CASE 24
TOKENIZE hold
us_min_phone_number_length = TOINT(GETTOKEN())
intl_min_phone_number_length = TOINT(GETTOKEN())
CASE 25
TOKENIZE hold
hold2 = UPPER(GETTOKEN())
IF (hold2 = "US" || hold2 = "BOTH") us_call_plan = TRUE
IF (hold2 = "INTL" || hold2 = "BOTH") THEN
intl_call_plan = TRUE
hold2 = UPPER(GETTOKEN())
IF (hold2 = "TRUE") prompt_for_zero = TRUE
END IF
CASE 26
IF (UPPER(hold) != "FALSE") drop_ld_cb = TRUE
END SELECT
'
' Increment configuration read counter
'
INC count
'
END WHILE
'
' Done...Close the file
'
FCLOSE 1
RETURN
'
' Check to see if their security level is too high to use the program
'
:SECURITY_CHECK
IF (U_SEC > highest_sec_level_allowed) THEN
PRINTLN
PRINTLN "@X4FSecurity Level Too High@X0F....@X0EReturning to the BBS"
NEWLINE
FPUTLN 7, "**-->> Security Level too high = ", U_SEC
DELAY 36
GOTO EXIT_PROG
END IF
RETURN
'
' Check to see if the username is in the BAD-NAME.LST file
'
' Format of file is one username per line
'
:BAD_NAMES
'
' Check for existence of BAD NAMES file. If found, check file for
' a match to current username. If found display the file BADN and
' exit the PPE
'
hold2 = PPEPATH() + "BAD-NAME.LST"
IF (EXIST(hold2)) THEN
FPUTLN 7, "Checking Username against: BAD-NAME.LST"
FOPEN 1, hold2, O_RD, S_DN
'
' Read file till value is matched or EOF is reached
'
WHILE (1) DO
'
FGET 1, hold
IF (FERR(1)) BREAK
'
' If a comment, read the next line
'
IF (LEFT(hold,1) = "'") CONTINUE
'
' See if names match
'
IF (UPPER(TRIM(U_NAME()," ")) = UPPER(TRIM(hold," "))) THEN
DISPFILE PPEPATH() + "BADNAM", GRAPH+LANG+SEC
FPUTLN 7, "**-->> Matched name in: BAD-NAME.LST...Exit Callback"
DELAY 36
GOTO EXIT_PROG
END IF
'
END WHILE
'
' If we got to here, no matching name was found. Log
' the results and close the file
'
FPUTLN 7, " No match found in: BAD-NAME.LST"
FCLOSE 1
'
END IF
RETURN
'
' Ask user which phone number from USER record to use for Callback
'
:PROCESS_USER_RECORD_PHONE
NEWLINES 2
PRINTLN " @X0FYou have the following phone numbers in your user record"
NEWLINE
PRINTLN " @X0ABusiness/Data Phone Number@X0F: [@X0CD@X0F] - @X02", U_BDPHONE
PRINTLN " @X0AHome/Voice Phone Number @X0F: [@X0CH@X0F] - @X02", U_HVPHONE
'
' Optional prompt to display to user. Will allow
' them to use an "other" phone number for callback.
'
IF (use_other) PRINTLN " @X0AUse Other Phone Number @X0F: [@X0CO@X0F]@X03ther"
NEWLINE
'
' Allow the "O" character to be used for a response when the
' user is prompted for which phone number to use for callback
'
IF (use_other) THEN
main_prompt = " Which number do you wish to use for your callback number (D/H/O)"
user_input = "D"
INPUTSTR main_prompt, user_input, @X0E, 1,"DHO", FIELDLEN+GUIDE+LFAFTER+UPCASE
ELSE
main_prompt = " Which number do you wish to use for your callback number (D/H)"
user_input = "D"
INPUTSTR main_prompt, user_input, @X0E, 1,"DH", FIELDLEN+GUIDE+LFAFTER+UPCASE
END IF
'
' Retrieve and "clean" data and voice user record phone numbers
'
GOSUB PREPARE_DATA_VOICE_NUMBERS
'
' User did not choose OTHER, so process their request for
' proper phone number
'
IF (user_input != "O") THEN
improper_user_rec_phone = FALSE
'
' Set variables and log information depending on
' if the user decided to use their voice or data
' phone number for callback.
IF (user_input = "D") phone_number = d_phone_number
IF (user_input = "H") phone_number = h_phone_number
'
' Set length to check user record phone number
'
IF (cp_required = 1) THEN
ck_length = us_min_phone_number_length
ELSE IF (cp_required = 2) THEN
ck_length = intl_min_phone_number_length
END IF
'
' Check if the phone number in the USERS RECORD is at
' equal to ck_length characters long (defined in configuration).
' If not inform user by displaying information, then
' allowing the user to enter in their phone number
' manually.
'
IF (LEN(phone_number) != ck_length) THEN
NEWLINE
PRINTLN " @X0FImproper phone number in user file - @X0CSysOp Notified@X0F!!@X07"
IF (user_input = "D") FPUTLN 7, "**-->> (D) Improper phone number in user file: ", U_BDPHONE
IF (user_input = "H") FPUTLN 7, "**-->> (H) Improper phone number in user file: ", U_HVPHONE
improper_user_rec_phone = TRUE
phone_number = ""
DELAY 54
ELSE
user_record_phone = TRUE
IF (user_input = "D") FPUTLN 7, " Phone number used: Data Number from User Record"
IF (user_input = "H") FPUTLN 7, " Phone number used: Voice Number from User Record"
END IF
'
' Break up phone number into component parts depending
' on calling plan
'
IF (user_record_phone && cp_required = 1) THEN
area_code = MID(phone_number, 1, 3)
exchange = MID(phone_number, 4, 3)
last_4_nums = MID(phone_number, 7, 4)
log_entry = area_code + "-" + exchange + "-" + last_4_nums
ELSE IF (user_record_phone && cp_required = 2) THEN
country_code = TRIM(MID(phone_number, 1, 3)," ")
exchange_code = TRIM(MID(phone_number, 4, 4)," ")
last_nums = TRIM(MID(phone_number, 8, 8)," ")
log_entry = country_code + "-" + exchange_code + "-" + last_nums
END IF
'
ELSE
FPUTLN 7, " Phone number used: User Entered 'OTHER' Phone Number"
END IF
RETURN
'
' Prompt user for their phone number -OR- check phone number
' user used from their USER RECORD entry
'
:GET_PROCESS_PHONE_NUMBER
'
' Clear out variables to accept new phone number only if we
' are NOT using phone numbers from user record
'
IF (!user_record_phone && cp_required = 1) THEN
area_code = ""
exchange = ""
last_4_nums = ""
ELSE IF (!user_record_phone && cp_required = 2) THEN
country_code = ""
exchange_code = ""
last_nums = ""
END IF
'
' Prompt/process AREACODE, EXCHANGE, & LAST 4 when we are
' using the US calling plan, COUNTRY CODE, CITY CODE & LAST
' when we are using INTL calling plan
'
'
' Get AREACODE/COUNTRY CODE
'
IF (cp_required = 1) THEN
main_prompt = " @X0APlease enter your Area Code: @X0F"
IF (area_code = "") NEWLINE
user_input = area_code
ck_length = 3
inp_length = 3
ELSE IF (cp_required = 2) THEN
main_prompt = "@X0APlease enter your Country Code: @X0F"
IF (country_code = "") NEWLINE
user_input = country_code
ck_length = 1
inp_length = 3
END IF
WHILE (LEN(user_input) < ck_length) DO
user_input = ""
INPUTSTR main_prompt, user_input, @X0F, inp_length, MASK_NUM(), FIELDLEN+GUIDE+LFAFTER
END WHILE
IF (cp_required = 1) THEN
area_code = user_input
FPUTLN 7, " Area Code: ", area_code
trash_type = 1
ELSE IF (cp_required = 2) THEN
country_code = user_input
FPUTLN 7, " Country Code: ", country_code
trash_type = 4
END IF
'
' Check TrashCan for AreaCode/Country Code Violation
'
GOSUB TRASH_CAN
'
' Check to see if we are to use AREACODE.DAT or CNTYCODE.DAT and then
' check to see if area code entered by user is found in the file
'
' found1 = FALSE when no match was found
'
IF (ck_area_code) THEN
GOSUB CHECK_AREA_CODE
ELSE
found1 = TRUE
END IF
'
' Users area code was not allowed for long distance calling so abort
'
IF (!found1) THEN
PRINTLN
IF (cp_required = 1) THEN
PRINTLN "@X0CArea Code @X0E" + area_code + "@X0C Is Not Allowed For Call Back@X07"
FPUTLN 7, " Area Code not in .DAT = ", area_code
LOG "** Area Code Not allowed in Callback **", FALSE
ELSE IF (cp_required = 2) THEN
PRINTLN "@X0CCountry Code @X0E" + country_code + "@X0C Is Not Allowed For Call Back@X07"
FPUTLN 7, "Country Code not in .DAT = ", country_code
LOG "** Country Code Not allowed in Callback **", FALSE
END IF
NEWLINE
PRINTLN "@X0BInform the sysop if you believe there is a problem, Thanks.@X07"
DELAY 36
GOTO EXIT_PROG
ELSE
found1 = FALSE
END IF
'
' Force user to enter a three digit exchange for US
' dialing plan, or up to a 4 digit city code for INTL
' dialing plan
'
' Get EXCHANGE/CITY CODE
'
IF (cp_required = 1) THEN
main_prompt = " @X0AEnter your Exchange: @X0F"
user_input = exchange
ck_length = 3
inp_length = 3
ELSE IF (cp_required = 2) THEN
main_prompt = " @X0AEnter your City Code: @X0F"
user_input = exchange_code
ck_length = 1
inp_length = 4
END IF
WHILE (LEN(user_input) < ck_length) DO
user_input = ""
INPUTSTR main_prompt, user_input, @X0F, inp_length, MASK_NUM(), FIELDLEN+GUIDE+LFAFTER
END WHILE
IF (cp_required = 1) THEN
exchange = user_input
FPUTLN 7, " Exchange: ", exchange
trash_type = 2
ELSE IF (cp_required = 2) THEN
exchange_code = user_input
FPUTLN 7, " City Code: ", exchange_code
trash_type = 5
END IF
'
' Check TrashCan for Exchange Violation
'
GOSUB TRASH_CAN
'
' If US Dialing plan see if xxxXCHNG.DAT files are to be used
'
IF (cp_required = 1 && !intl_callback) THEN
'
' Check Exchange for local or long distance call to be made
' Check to see if area code is ALWAYS a local call (from .CFG file)
'
IF (INSTR(area_code_local,area_code) = 0) THEN
IF (ck_exchange) GOSUB CHECK_EXCHANGE ' found1 = TRUE if match found
ELSE
found1 = TRUE
END IF
'
' If checking for the xxxXCHNG.DAT file and the
' exchange is found (found1 = TRUE), it is a
' local call
'
IF (ck_exchange) THEN
IF (found1) THEN
local_call = TRUE
hold = "TRUE"
ELSE
local_call = FALSE
hold = "FALSE"
END IF
FPUTLN 7, " Local Call: ", hold
END IF
END IF ' cp_required = 1
'
' Get last 4 or last 8 numbers
'
IF (cp_required = 1) THEN
main_prompt = " @X0AEnter the last 4 digits: @X0F"
user_input = last_4_nums
ck_length = 4
inp_length = 4
ELSE IF (cp_required = 2) THEN
main_prompt = " @X0AEnter remaining numbers: @X0F"
user_input = last_nums
ck_length = 1
inp_length = 8
END IF
WHILE (LEN(user_input) < ck_length) DO
user_input = ""
INPUTSTR main_prompt, user_input, @X0F, inp_length, MASK_NUM(), FIELDLEN+GUIDE+LFAFTER
END WHILE
IF (cp_required = 1) THEN
last_4_nums = user_input
FPUTLN 7, " Last 4 Numbers: ", last_4_nums
trash_type = 3
ELSE IF (cp_required = 2) THEN
last_nums = user_input
FPUTLN 7, " Last Numbers: ", last_nums
trash_type = 6
END IF
'
' Check TrashCan for Last 4 number Violation
'
GOSUB TRASH_CAN
' If "area_code" equals the "area_code_local" (always a local call)
' then do not propmt the user for local or long distance, the call
' is ALWAYS a local call.
'
'
' This section will either ask the user if the call is local
' or long distance or the program will automatically set the
' local_call variable for true or false (based on xxxXCHNG.DAT)
'
IF (cp_required = 1 && !intl_callback) THEN
IF (!ck_exchange) THEN
IF (area_code != area_code_local) THEN
GOSUB ASK_LOCAL_LD
ELSE
local_call = TRUE
FPUTLN 7, " Local Call: ALWAYS TRUE AREACODE"
END IF
END IF
ELSE IF (cp_required = 1 && intl_callback) THEN
local_call = FALSE
ELSE IF (cp_required = 2) THEN
IF (!intl_callback) THEN
GOSUB ASK_LOCAL_LD
IF (prompt_for_zero) THEN
'
' In the U.K. you need to add a leading 0 to the dialing code
' when making a phone call within the U.K. to another part of
' the U.K.
'
PRINTLN "@X0ESome countries require a '0' to preceed the phone number to"
PRINTLN "make a phone call within the same country. With this in mind..."
main_prompt = "@X0ADoes this call to you, require a '0' to preceed the number@X07"
hold2 = NOCHAR()
INPUTYN main_prompt, hold2, @X0E
IF (hold2 = YESCHAR()) exchange_code = "0" + exchange_code
NEWLINE
END IF
ELSE
local_call = FALSE
END IF
END IF
'
' Build phone number variables (phone_number, log_entry) - used later on
'
IF (cp_required = 1) THEN
phone_number = area_code + exchange + last_4_nums
log_entry = area_code + "-" + exchange + "-" + last_4_nums
ELSE IF (cp_required = 2) THEN
phone_number = country_code + exchange_code + last_nums
log_entry = country_code + "-" + exchange_code + "-" + last_nums
END IF
'
' Log the phone number the user entered
'
FPUTLN 7, " Phone Number Entered: ", log_entry
RETURN
'
' Ask the user if the call is LOCAL or Long Distance
'
:ASK_LOCAL_LD
'
' Build string to prompt the user - Default answer = YES - Local call
'
NEWLINE
main_prompt = " @X0C" + log_entry + "@X0F - @X0EIs this a Local Phone Call @X0F(@X02Y/N@X0F)"
hold2 = YESCHAR()
'
' Prompt and get yes/no response from user
'
INPUTYN main_prompt, hold2, @X0E
'
' Read response and look for LANGUAGE SPECIFIC "YES" answer
'
IF (hold2 = YESCHAR()) THEN
local_call = TRUE
FPUTLN 7, " Local Call: TRUE - CHOSEN BY USER"
ELSE
local_call = FALSE
FPUTLN 7, " Local Call: FALSE - CHOSEN BY USER"
END IF
NEWLINE
RETURN
'
' See if the call is local or LD and check the times allowed to call
'
:CK_ALLOWED_TIMES
'
' Check for Local or LD call, and determine if current time
' is within callback time. The flag file no_call will be set
' to TRUE if callback is not allowed at the current time.
'
no_call = FALSE
IF (local_call) THEN
'
' Local Call
'
IF (local_end_time < local_start_time) THEN
IF (TIME() < local_start_time && TIME() > local_end_time) no_call = TRUE
ELSE IF (local_end_time > local_start_time) THEN
IF (TIME() < local_start_time || TIME() > local_end_time) no_call = TRUE
END IF
'
' Log information
'
FPUTLN 7, " Local Allowed Start Time: ", local_start_time
FPUTLN 7, " Local Allowed End Time: ", local_end_time
FPUTLN 7, " Current time is: ", TIME()
'
END IF
'
IF (!local_call && !block_ld_callbacks) THEN
'
' Long Distance Call
'
IF (ld_end_time < ld_start_time) THEN
IF (TIME() < ld_start_time && TIME() > ld_end_time) no_call = TRUE
ELSE IF (ld_end_time > ld_start_time) THEN
IF (TIME() < ld_start_time || TIME() > ld_end_time) no_call = TRUE
END IF
'
' Log information
'
FPUTLN 7, " LD Allowed Start Time: ", ld_start_time
FPUTLN 7, " LD Allowed End Time: ", ld_end_time
FPUTLN 7, " Current time is: ", TIME()
'
ELSE IF (!local_call && block_ld_callbacks) THEN
'
' If callback is outside allowed hours -OR- the sysop
' is blocking all Long Disntance callbacks, show file (LCNO/LDNO)
' informing user and exit the callback program
'
FPUTLN 7, " Long Distance Callback Blocked - ** No Callback performed **"
DISPFILE PPEPATH() + "ldno", LANG+GRAPH+SEC
local_call = TRUE
GOTO EXIT_PROG
'
END IF
IF (no_call) THEN
FPUTLN 7, " Callback within hours: FALSE - ** No Callback performed **"
IF (local_call) THEN
DISPFILE PPEPATH() + "lcno", LANG+GRAPH+SEC
ELSE
DISPFILE PPEPATH() + "ldno", LANG+GRAPH+SEC
END IF
local_call = TRUE
GOTO EXIT_PROG
END IF
'
' Call back is within allowed hours. Add to LOG
'
FPUTLN 7, " Callback within hours: TRUE"
RETURN
'
' Open the proper security file for local or long distance caller
'
:READ_SECURITY_FILE
'
' Check for existence of security files. If found Open the files,
' if not found, inform caller and log error.
'
found1 = FALSE
IF (local_call) THEN
IF (!EXIST(PPEPATH() + "LC-SL.CFG")) THEN
NEWLINES 3
PRINTLN "Local Security File MISSING - Inform SysOp Immediately!!"
FPUTLN 7, "**-->> Local Security (LC-SL.CFG) File MISSING!!"
DELAY 54
GOTO EXIT_PROG
END IF
FOPEN 1, PPEPATH() + "LC-SL.CFG", O_RD, S_DN
ELSE
IF (!EXIST(PPEPATH() + "LD-SL.CFG")) THEN
NEWLINES 3
PRINTLN "Long Distance Security File MISSING - Inform SysOp Immediately!!"
FPUTLN 7, "**-->> Long Distance Security (LD-SL.CFG) File MISSING!!"
DELAY 54
GOTO EXIT_PROG
END IF
FOPEN 1, PPEPATH() + "LD-SL.CFG", O_RD, S_DN
END IF
'
' Find the matching security level and assign the appropriate
' security levels and expiration dates for success and failure
' of callback,
'
WHILE (1) DO
'
' Get line from ??-SL.CFG file
'
FGET 1, hold
'
' If error reading from file (end of file), users security level
' *probably* was not matched -OR- the ??-SL.CFG file was not present.
'
IF (FERR(1)) THEN
IF (!found1) THEN
LOG "*** Cannot find matching security level in ??-SL.CFG", FALSE
FPUTLN 7, "*** Cannot find matching security level in ??-SL.CFG"
NEWLINES 3
PRINTLN "@X0CYour security level was not found by program - @X0FInform SysOp ASAP!!!@X07"
NEWLINES 2
WAIT
local_call = TRUE
GOTO EXIT_PROG
END IF
END IF
'
' If comment line, read the next line
'
IF (LEFT(hold,1) = "#" || LEFT(hold,1) = "'") CONTINUE
'
' See if we match the users security level. If we match
' then read in all the parameters into their variables
'
IF (U_SEC = TOINT(MID(hold, 1, INSTR(hold,";")-1))) THEN
'
' Tokenize the line we retrieved from security file
' and get the component parts and assign to proper
' variables.
'
found1 = TRUE
TOKENIZE hold
'
' Put matching security level (1st parmameter) into generic variable
' as we dont need it
'
user_input = GETTOKEN()
'
' Retreive remaining parameters
'
verified_level = TOINT(GETTOKEN())
failure_level = TOINT(GETTOKEN())
expired_level = TOINT(GETTOKEN())
adjust_mins = TOINT(GETTOKEN())
expired_date_days = TOINT(GETTOKEN())
'
' Log information about security levels
'
FPUTLN 7, " Verified Sec Level: ", verified_level
FPUTLN 7, " Failure Sec Level: ", failure_level
FPUTLN 7, " Expired Sec Level: ", expired_level
FPUTLN 7, " Time Adjustment: ", adjust_mins
'
' Log what the user new expiration date will be
'
IF (expired_date_days != 0) THEN
FPUT 7, " Days till Expired Date: ", expired_date_days, " = ", TODATE(DATE() + expired_date_days)
ELSE
FPUT 7, " Days till Expired Date: ", expired_date_days, " = 00/00/00"
END IF
FPUTLN 7, " - (If Callback is successful)"
'
' Exit routine due to finding security level match
'
BREAK
ELSE
CONTINUE
END IF
'
END WHILE
FCLOSE 1
RETURN
'
' Search VERIFIED.LOG for verified phone numbers
'
:CK_VERIFIED_LOG
do_increase = FALSE
PRINT "@X02Checking entries in verified log for duplicates: @X0F"
count = 0
PRINT " "
'
' Check for existance of VERIFIED.LOG
'
IF (!EXIST(PPEPATH() + "VERIFIED.LOG")) THEN
FPUTLN 7, "**-->> VERIFIED.LOG is not found"
RETURN
END IF
'
' Verified.Log file found. Check to see if user has
' already been verified.
'
FOPEN 1, PPEPATH() + "VERIFIED.LOG", O_RD, S_DN
WHILE (1) DO
'
' Retrieve an entry from the verified.log file
'
FGET 1,hold
'
' IF (EOF), or error, stop reading the file.
'
IF (FERR(1)) BREAK
INC count
'
' See if entry is an international entry. If it is
' and we are processing cp_required = 1 (US) read
' the next line. If cp_required = 2 (INTL) strip
' the leading "*".
'
IF (LEFT(hold,1) = "*" && cp_required = 1) CONTINUE
'
' If we have checked 100 entries, display to the user so they
' know the program is doing something
'
IF (!(count % 100)) PRINT CHR(8), CHR(8), CHR(8), CHR(8), SPACE(4-LEN(count)), count
'
' Retrieve phone number field from verified log entry
' and check for an already verified number. If found
' set flag FOUND1 = TRUE
'
IF (cp_required = 1) THEN
hold2 = MID(hold, 1, 12)
ELSE IF (cp_required = 2) THEN
hold2 = MID(hold, 2, 24)
END IF
'
' See if phone number in log matches depending on dialing plan
'
IF (cp_required = 1) THEN
IF (hold2 = log_entry) found1 = TRUE
ELSE IF (cp_required = 2) THEN
IF (RTRIM(hold2," ") = log_entry) found1 = TRUE
END IF
'
' Found a match if FOUND1 = TRUE
'
IF (found1) THEN
'
' See if username matched
'
IF (cp_required = 1) THEN
start_read = 14
ELSE IF (cp_required = 2) THEN
start_read = 26
END IF
IF (MID(hold, start_read, LEN(TRIM(U_NAME()," "))) = TRIM(U_NAME()," ") && RIGHT(MID(hold,start_read,LEN(TRIM(U_NAME()," "))+1), 1) = " ") THEN
'
' If up_already_verified is TRUE then the user will be upgraded
' without having to go through the callback process again. They
' are a previously verified user.
'
IF (up_already_verified) THEN
NEWLINES 3
DISPFILE PPEPATH() + "AL-VER", GRAPH+LANG+SEC
LOG "** User already Verified - Upgraded Security **", FALSE
FPUTLN 7, "**-->> User already verified before"
FPUTLN 7, "**-->> Verified entry = ", MID(hold,start_read,LEN(U_NAME()))
'
' Set password input to current password
' Set flag for already verified to TRUE
'
password_input = U_PWD
username_input = U_NAME()
already_verified = TRUE
WAIT
FCLOSE 1
'
' Set flag TRUE, so users gets a security level increase
'
do_increase = TRUE
BREAK
'
ELSE
'
' Make user do verification again
'
BREAK
'
END IF
END IF
NEWLINES 3
'
' Callback number has already been used by another user
' Display file to user informing them of this conflict.
'
DISPFILE PPEPATH() + "DUPNUM", GRAPH+LANG+SEC
LOG "** Duplicate Number - Security Not Changed **", FALSE
FPUTLN 7, "~~~~~~Duplicate number found in verified.log~~~~~~ : ", MID(hold,1,12)
FPUTLN 7, " Duplicate entry info: ", hold
WAIT
GOTO EXIT_PROG
END IF
END WHILE
FCLOSE 1
RETURN
'
' Set timeout for local and LD from configuration file and
' build number for modem to dial
'
:SET_DURATION_BUILD_MODEM_DIAL
' Build sting to send to modem for dialing
'
' dialing_string = ATDT/ATDP
' dialing_prefix = additional number to dial out
' ld_prefix = number used to dial a long distance phone number
' intl_ld_prefix = number used to dial an international phone number
'
IF (cp_required = 1) THEN
IF (local_call) THEN
'
' If local call which does not require areacode,
' just dial exchange + last 4
'
IF (INSTR(local_no_area_code, area_code)) THEN
send_modem = dialing_string + dialing_prefix + exchange + last_4_nums
ELSE
'
' else, dial areacode, exchange + last 4 for local call
'
'
send_modem = dialing_string + dialing_prefix + phone_number
END IF
ELSE
IF (intl_callback) THEN
'
' cp_required = 1 is always country code "1"
'
hold2 = intl_ld_prefix + "1"
ELSE
'
' Long distance call (US to US)
'
hold2 = ld_prefix
END IF
'
' Build string
'
send_modem = dialing_string + dialing_prefix + hold2 + phone_number
END IF
ELSE IF (cp_required = 2) THEN
'
' INTL dialing plan
'
IF (local_call) THEN
'
' Local call = (Ex Code + Last Nums)
'
send_modem = dialing_string + dialing_prefix + exchange_code + last_nums
ELSE
'
' LD Call = (LD Prefix + Country Code + Ex Code + Last Nums)
'
send_modem = dialing_string + dialing_prefix + intl_ld_prefix + phone_number
END IF
END IF
'
' Set duration of each callback depending on local or LD
'
IF (local_call) THEN
duration_to_call = local_time_to_call
ELSE
duration_to_call = ld_time_to_call
END IF
'
' See if "suffix" variable has a value.
'
' Add to send_modem varualbe if suffix value is not blank.
'
IF (dialing_suffix != "") THEN
IF (suffix_use = "A") THEN
send_modem = send_modem + dialing_suffix
ELSE IF (suffix_use = "L" && local_call) THEN
send_modem = send_modem + dialing_suffix
ELSE IF (suffix_use = "D" && !local_call) THEN
send_modem = send_modem + dialing_suffix
END IF
END IF
IF (!ONLOCAL()) FPUTLN 7, " Dialing String to Modem: ", send_modem
RETURN
'
' Make callback
'
:PERFORM_CALL
'
'
'
CDCHKOFF
KBDCHKOFF
KBDFLUSH
MDMFLUSH
DTROFF
DELAY 18
'
' Display on local screen
'
DISPFILE PPEPATH() + "CALLB", GRAPH+SEC+LANG
'
'
'
COLOR @X0F
ANSIPOS 19,7
IF (local_call) THEN
SPRINT "TRUE"
ELSE
SPRINT "FALSE"
END IF
'
'
'
ANSIPOS 41,7
SPRINT SPACE(3-LEN(duration_to_call)), duration_to_call
COLOR @X0F
current_timeout_value = 0
GOSUB SHOW_TIMEOUT_COUNTDOWN
'
'
'
WHILE (cb_remain_number > 0 && !made_connection) DO
'
' Drop DTR, Raise DTR
'
GOSUB MODEM_INIT
'
' Check for SysOp interrupt - Carriage Return or Space Bar
'
' Carriage Return - Stops the Callback program
' Space Bar - Recycles the Callback program - Starts another call
'
GOSUB CHECK_SYSOP_KEY
IF (hold = 32 || hold = CHR(32)) CONTINUE
'
' Send INIT String to modem
'
COLOR @X0E
ANSIPOS 26,11
SPRINT MID("AT" + init_string, 1, 25)
ANSIPOS 26,11
SENDMODEM "AT" + init_string + CHR(13)
DELAY 18
'
' Display information on LOCAL screen
'
COLOR @X8D
ANSIPOS 26,12
SPRINT cb_remain_number, SPACE(3-LEN(cb_remain_number))
FPUTLN 7, " Callback Attempt: Started @ ", STRING(TIME())
'
' Set starting time for callback timeout watch
'
start_time = TIME()
'
' Dial the modem - show number called on CALLB display
'
modem_string = ""
COLOR @X03
ANSIPOS 26,13
SPRINT log_entry ' displays phone number with HYPHENS
SENDMODEM send_modem + CHR(13)
'
' Display 'Waiting' in Modem return field
'
ANSIPOS 26,14
COLOR @X02
SPRINT "Waiting..."
ANSIPOS 26,14
'
' Loop to monitor modem results (ring, busy, connect, no dialtone)
'
WHILE (1) DO
end_time = TIME()
'
' Check to see if the timeout value has been exceeded
'
IF (end_time > (start_time + duration_to_call)) THEN
DEC cb_remain_number
'
' Clear the display fields for next call
'
GOSUB CLEAR_CALLB
current_timeout_value = 0
GOSUB SHOW_TIMEOUT_COUNTDOWN
FPUTLN 7, " Modem results: **-->> Callback Timeout...."
BREAK
ELSE
GOSUB SHOW_TIMEOUT_COUNTDOWN
END IF
'
' Check for SysOp interrupt - Carriage Return or Space Bar
'
' Carriage Return - Stops the Callback program
' Space Bar - Recycles the Callback program - Starts another call
'
GOSUB CHECK_SYSOP_KEY
IF (hold = 32 || hold = CHR(32)) BREAK
'
' Gather bytes from modem to determine matching string
' Make sure we do not gather Carriage Returns or Line Feeds
'
modem_byte = MGETBYTE()
DELAY 2
'
' -1 is returned when there is no byte to get from Modem
'
IF (modem_byte != -1) THEN
'
' If not a CR or LF, add the character to the modem_string variable
'
IF (modem_byte != 10 && modem_byte != 13) modem_string = modem_string + CHR(modem_byte)
'
' See if we have a CONNECT message from modem
'
IF (INSTR(modem_string, "CONNECT")) THEN
modem_string = modem_string + CHR(MGETBYTE())
'
' Get actual connect rate and ARQ to display to SysOp
'
WHILE (1) DO
modem_byte = MGETBYTE()
IF (modem_byte = -1) BREAK
modem_string = modem_string + CHR(modem_byte)
END WHILE
'
' Display connect message on local screen
'
COLOR @X0F
ANSIPOS 26,14
IF (LEN(modem_string) > 45) modem_string = MID(modem_string, 1, 45)
SPRINT modem_string
ANSIPOS 26,14
made_connection = TRUE
BREAK
'
' See if we have a BUSY message from modem
'
ELSE IF (INSTR(modem_string, "BUSY")) THEN
'
' Display Modem message
'
COLOR @X0F
ANSIPOS 26,14
SPRINT modem_string + SPACE(20-LEN(modem_string))
ANSIPOS 26,14
SENDMODEM "ATH0" + CHR(13)
DELAY 18
current_timeout_value = 0
GOSUB SHOW_TIMEOUT_COUNTDOWN
GOSUB CLEAR_CALLB
FPUTLN 7, " Modem results: Busy...let's try again"
COLOR @X07
cb_remain_number = cb_remain_number - busy_value
BREAK
'
' See if we have NO DIALtone from Modem
'
ELSE IF (INSTR(modem_string, "NO DIAL")) THEN
'
' Display Modem message
'
COLOR @X0F
ANSIPOS 26,14
SPRINT modem_string + SPACE(20-LEN(modem_string))
ANSIPOS 26,14
DELAY 18
current_timeout_value = 0
GOSUB SHOW_TIMEOUT_COUNTDOWN
GOSUB CLEAR_CALLB
COLOR @X0C
FPUTLN 7, " Modem results: No Dialtone...let's try again"
COLOR @X07
cb_remain_number = cb_remain_number - no_dial_value
BREAK
'
' See if we have an INCOMING call from Modem
'
ELSE IF (INSTR(modem_string, "RING")) THEN
'
' Display Modem message
'
COLOR @X0F
ANSIPOS 26,14
SPRINT modem_string + SPACE(20-LEN(modem_string))
ANSIPOS 26,14
COLOR @X8C
ANSIPOS 3,18
SPRINT "***** "
COLOR @X0F
SPRINT "INCOMING CALL - TERMINATE!!! "
COLOR @X8C
SPRINT "*****"
'
' Pick up the call, then drop DTR to hang up
'
COLOR @X0A
ANSIPOS 3,18
SPRINT "Pick up phone, "
COLOR @X0F
SPRINT "drop DTR <G>, "
COLOR @X0A
SPRINT "bye bye incoming..."
ANSIPOS 3,18
SENDMODEM "ATH1" + CHR(13)
DELAY 54
current_timeout_value = 0
GOSUB SHOW_TIMEOUT_COUNTDOWN
'
' Clear screen display fields
'
GOSUB CLEAR_CALLB
'
' Drop DTR, raise DTR
'
GOSUB MODEM_INIT
FPUTLN 7, " Modem results: Incoming Call...let's try again"
cb_remain_number = cb_remain_number - ring_value
'
' Break out of Modem pooling loop to start
' another callback due to a non-connect
'
BREAK
END IF
END IF
END WHILE
'
' Clear the display fields for next call
'
current_timeout_value = 0
GOSUB SHOW_TIMEOUT_COUNTDOWN
IF (INSTR(modem_string, "CONNECT") = 0) GOSUB CLEAR_CALLB
CONTINUE
END WHILE
RETURN
'
' Stop checking for carrier, and Keyboard
' Flush modem and Keyboard Buffers
' Drop DTR, Raise DTR, send modem init commands
'
:MODEM_INIT
CDCHKOFF
KBDCHKOFF
KBDFLUSH
MDMFLUSH
DTROFF
ANSIPOS 26,9
COLOR @X0C
SPRINT "Active "
ANSIPOS 26,9
DELAY 72
COLOR @X0F
SPRINT "Done "
ANSIPOS 26,10
DTRON
COLOR @X0C
SPRINT "Active "
ANSIPOS 26,10
DELAY 9
COLOR @X0F
SPRINT "Done "
RETURN
'
' Ask the user for their Password as verification
'
:ASK_VERIFY_VERIFICATION_INFO
'
' Initialize variables and clear the screen
'
password_input = ""
username_input = ""
do_increase = FALSE
int_count = 1
CLS
'
' Display proper screen depending on verification_type
'
IF (verification_type = "BOTH") DISPFILE PPEPATH() + "getpwun", LANG+GRAPH+SEC
IF (verification_type = "USER") DISPFILE PPEPATH() + "getun", LANG+GRAPH+SEC
IF (verification_type = "PASS") DISPFILE PPEPATH() + "getpw", LANG+GRAPH+SEC
'
' Clear out any waiting characters, and ask for username/password
'
KBDFLUSH
MDMFLUSH
'
' Ask for username verification
'
IF (verification_type = "BOTH" || verification_type = "USER") THEN
'
WHILE (!username_correct) DO
'
' Check to see if user has exceeded allowed verification attempts
'
IF (int_count > verification_entry_count) GOTO EXCEED_TRIES
'
' Prompt user for their username they logged on with
'
main_prompt = " Enter Username"
INPUTSTR main_prompt, username_input, @X0E, 25, MASK_ASCII(), UPCASE+FIELDLEN+LFAFTER
'
' If username is wrong, inform user and show how many attempts are
' remaining to enter correct username
'
IF (username_input <> U_NAME()) THEN
PRINT " @X0CIncorrect Username@X0F!!!...@X0BPlease try again. @X0C[@X0E"
PRINTLN verification_entry_count - int_count, "@X0C] @X0Btries remaining"
FPUTLN 7, " Incorrect Username: " + username_input
INC int_count
username_input = ""
DELAY 18
ELSE
username_correct = TRUE
IF (verification_type != "BOTH") THEN
do_increase = TRUE
BREAK
END IF
END IF
END WHILE
END IF
'
' Ask for Password verification
'
IF (verification_type = "BOTH" || verification_type = "PASS") THEN
WHILE (!password_correct) DO
'
' Check to see if user has exceeded allowed verification attempts
'
IF (int_count > verification_entry_count) GOTO EXCEED_TRIES
'
' Prompt user for their password they logged on with
'
main_prompt = " Enter Password"
INPUTSTR main_prompt, password_input, @X0E, 12, MASK_ASCII(), UPCASE+ECHODOTS+FIELDLEN+LFAFTER
'
' If password is wrong, inform user and show how many attempts are
' remaining to enter correct password
'
IF (password_input <> U_PWD) THEN
PRINT " @X0CIncorrect Password@X0F!!!...@X0BPlease try again. @X0C[@X0E"
PRINTLN verification_entry_count - int_count, "@X0C] @X0Btries remaining"
FPUTLN 7, " Incorrect Password: " + password_input
INC int_count
password_input = ""
DELAY 18
ELSE
password_correct = TRUE
do_increase = TRUE
BREAK
END IF
END WHILE
END IF
RETURN
'
' User exceeded their verification information attempts.
' Disconnect the user from the BBS and log it
'
:EXCEED_TRIES
NEWLINE
DISPFILE PPEPATH() + "FAL-SEC", GRAPH+LANG+SEC
FPUTLN 7, "**-->> Excessive Verification Attempts - Disconnecting User"
LOG "** Excessive Verification Attempts - Security Level Not Changed **", FALSE
'
' Update users security to "FAILED" security level
'
U_SEC = failure_level
FPUTLN 7, " Security Level set to: " + STRING(failure_level)
PUTUSER
DELAY 54
'
' Close Log file
'
GOSUB CLOSE_LOG
IF (!ONLOCAL()) THEN
HANGUP
ELSE
PRINTLN "Local Testing - User stays online"
FPUTLN 7, "Local Testing - User stays online"
END IF
END ' Not needed but have it here for end of subroutine marker
'
' User entered correct username/password so tell'm whats up and add
' their phone number to vierified file, raise their security level and
' add days to their date expiration (if configured).
'
:INCREASE_LEVEL
IF (do_increase) THEN
'
IF (U_SEC < verified_level || ONLOCAL()) THEN
'
' Set the users security level to the VERIFIED SECURITY LEVEL
'
U_SEC = verified_level
'
' Set the users expired security level
'
U_EXPSEC = expired_level
'
' Set the users expiration date (if .CFG entry is not a blank line)
'
IF (expired_date_days != 0) THEN
U_EXPDATE = DATE() + expired_date_days
ELSE
U_EXPDATE = 0
END IF
'
' Check to see if
'
IF (post_cbinfo_user_record != "") GOSUB POST_COMMENT_NOTES
'
' Write new information to users record, and inform user
' of a successful callback.
'
PUTUSER
'
' Adjust (add/subtract) users time based on security level entry
'
ADJTIME adjust_mins
'
' Import message into Message base
'
IF (msg_text_file != "") MESSAGE msg_conf_num, "SYSOP", "CB-FREE Callback PPE", MIXED(U_NAME()) + " - Completed Callback", "R", 0, FALSE, FALSE, msg_text_file
'
' Clear the screen and inform user of their security level upgrade
'
CLS
'
' Display file to user informing them that a callback will
' not be required as their CID information matches the
' number in their user record. This file will display only
' if it exists
'
IF (cid_matches_user && EXIST(PPEPATH() + "CID-USR")) DISPFILE PPEPATH() + "CID-USR", GRAPH+LANG+SEC
'
' If the file PAS-SEC exists, display it after showing user their
' security level has been upgraded. (Passed Callback Security Level)
'
NEWLINE
IF (EXIST(PPEPATH() + "PAS-SEC")) DISPFILE PPEPATH() + "PAS-SEC", GRAPH+LANG+SEC
'
' If the user is not already verified, add them to the VERIFIED.LOG
'
IF (!already_verified) THEN
'
' Loop incase VERIFIED.LOG is being used by another node. If
' the file is in use, we will pause approx. 1 second and try again
' up to 10 times.
'
FOR int_count = 1 TO 10
'
' Add the verified number to the VERIFIED.LOG file
'
FAPPEND 1,PPEPATH() + "VERIFIED.LOG", O_WR, S_DW
'
' If we get an error trying to open VERFIFIED.LOG for write
' access, there is probably another node writing to the
' file. So, we will delay approximately 1 second and try
' again.
'
IF (FERR(1)) THEN
COLOR @X0F
NEWLINE
SPRINTLN "Error opening VERIFIED.LOG - Pause 1 Sec and try again"
FPUTLN 7, "**-->> Error opening VERIFIED.LOG - Pause 1 Sec - try again"
COLOR @X07
DELAY 18
CONTINUE
END IF
'
' Right fill non "US" calling plan phone number with spaces
' so each entry is 25 characters in length and starts with
' an "*"
'
IF (cp_required = 2) log_entry = "*" + log_entry + SPACE(23-(LEN(log_entry)))
'
' Build entry to write to VERIFIED.LOG.
'
hold = log_entry + " " + U_NAME() + " " + STRING(TIME()) + " " + STRING(DATE())
'
' Append LOCAL, LONG DISTANCE, or INTERNATIONAL to entry
'
IF (intl_callback) THEN
hold = hold + "International"
ELSE
IF (local_call) THEN
hold = hold + " Local"
ELSE
hold = hold + " Long Distance"
END IF
END IF
'
' See if Caller ID in use, and we got a Caller ID Phone number
' If so, append it to the string posted to VERIFIED.LOG
'
IF (caller_id_info != "" && process_caller_id) hold = hold + " - CID # Used"
'
' Write the information to the log
'
FPUTLN 1, hold
'
' Check to see if Data or Voice phone number was used.
'
log_entry = STRIPSTR(log_entry, "-")
IF (log_entry != h_phone_number) GOSUB ADD_VOICE_TO_LOG
IF ((log_entry != d_phone_number) && (d_phone_number != h_phone_number)) GOSUB ADD_DATA_TO_LOG
'
' Close VERIFIED.LOG
'
FCLOSE 1
'
' Exit the FOR loop
'
BREAK
'
NEXT
'
END IF
'
' Determine what to print to NODE?.LOG file
'
IF (!already_verified) THEN
IF (verification_type = "BOTH") THEN
FPUTLN 7, "Matching Username/Password entered, Raise Security Level to " + STRING(verified_level)
ELSE IF (verification_type = "PASS") THEN
FPUTLN 7, "Matching Password entered, Raise Security Level to " + STRING(verified_level)
ELSE IF (verification_type = "USER") THEN
FPUTLN 7, "Matching Username entered, Raise Security Level to " + STRING(verified_level)
END IF
ELSE
FPUTLN 7, "Already Verified, Raise Security Level to " + STRING(verified_level)
END IF
'
' Write to PCB Callers File that users security was upgraded
'
LOG "%%% Users Security Upgraded %%%", FALSE
ELSE
'
' If users security level is GREATER THAN OR EQUAL TO the security
' file upgrade security level, inform the user there was no change
' made.
'
CLS
NEWLINES 6
PRINTLN "@X0ACallback completed@X0F....@X0ESecurity Level too High@X0F...@X0CSecurity not adjusted@X07"
FPUTLN 7, "**-->> Security Level not changed. Current Security Level too High"
'
END IF
END IF
'
' User was long distance so boot'em out of here to keep the
' LD charges from adding up any more.
'
IF (!local_call && !already_verified && drop_ld_cb) THEN
NEWLINE
PRINTLN "@X0CLong Distance Callback. .......@X0EDisconnecting now......"
PRINTLN "@X0FPlease call us right back to enjoy your increased access@X07"
FPUTLN 7, "Long Distance Call....Hanging up the phone"
LOG "** Long Distance - Disconnecting now... **", FALSE
DELAY 54
GOTO EXIT_PROG
END IF
'
' Make sure we log information telling the SysOp the user is
' a long distance callback, but they are allowed to remain online
'
' This is due to a configuration setting (#26) allowing this
'
IF (!local_call && !already_verified && !drop_ld_cb) THEN
FPUTLN 7, "Long Distance Callback.............User REMAINS online!"
FPUTLN 7, "Configuration Setting #26 (FALSE) allows this to occur!"
LOG "** Long Distance Callback - User REMAINS online!! **", FALSE
END IF
'
' local_call set to TRUE so HANGUP command does not
' get invoked in EXIT_PROG
'
local_call = TRUE
RETURN
'
' Prompt user to continue or go back to BBS
'
:BEGIN_CALLBACK
NEWLINE
user_input = ""
'
' If configuration not set to process caller ID, or
' the callerid string returns no information show
' the user their "user record" phone numbers and ask
' them to choose one for callback
'
IF (process_caller_id && cp_required = 1) GOSUB PROCESS_CALLER_ID_INFO
'
' Log User Security level, and Phone Number information.
'
FPUTLN 7, " User's Security Level: ", U_SEC
FPUTLN 7, " RAW User Rec. Data Phone: ", U_BDPHONE
FPUTLN 7, " RAW User Rec. Home Phone: ", U_HVPHONE
'
' Start loop to GET and PROCESS users phone number
'
WHILE (1) DO
'
' Check to see if user record info for voice and
' data phone numbers has a value other than nothing or spaces
'
user_record_phone = FALSE
'
' Check to see if user is "Re-Entering" their phone number. If so
' skip the user record choices and prompt for their phone number.
' The prompting for a phone number will only occur if:
'
' 1. Bad phone number in user record
' 2. SysOp has the "Other Phone Number" option turned on
'
IF (user_input != "R") THEN
'
' Check to see if user record phone numbers are available
'
IF (U_BDPHONE != "" || U_HVPHONE != "" || U_BDPHONE != SPACE(LEN(U_BDPHONE)) || U_HVPHONE != SPACE(LEN(U_HVPHONE))) THEN
'
' If no callerid info, or not processing callerid, or using INTL
' calling plan, get phone numbers from user record
'
IF (caller_id_info = "" || !process_caller_id || cp_required != 1) THEN
'
' If caller_id_info is blank -OR- we are not processing
' caller ID information, get phone numbers from user record
' and prompt the user as to which one they want to use for
' callback. CID only for US call plan.
'
GOSUB PROCESS_USER_RECORD_PHONE
'
ELSE
'
' Retrieve and "clean" data and voice user record phone numbers
'
GOSUB PREPARE_DATA_VOICE_NUMBERS
'
' strip all unwanted "telephone" characters from CID string
' (there shouldn't be any, but in case some modems do this)
'
hold = caller_id_info
GOSUB CLEAN_UP_NUMBER
'
' Log our "processed" CID string
'
FPUTLN 7, " Caller ID information: ", hold
'
' Put "clean" telephone information back in caller ID variable
'
caller_id_info = hold
'
' Prepare area code, exchange, and last 4 nums (from CID info)
'
area_code = MID(hold, 1, 3)
exchange = MID(hold, 4, 3)
last_4_nums = MID(hold, 7, 4)
log_entry = area_code + "-" + exchange + "-" + last_4_nums
'
' Set to true to bypass asking for "Other" phone number
' since neither the Home or Data phone number was chosen
' due to caller id being used
'
user_record_phone = TRUE
'
' Log which phone number we are using (data, voice, CID)
'
FPUTLN 7, " Phone number used: Caller ID"
'
END IF ' end of IF (CALLID()...
END IF ' end of processing USER RECORD phone numbers
END IF ' end of checking for Re-Enter
'
' Get "O"ther phone number and process *OR* process the phone
' number chosen from their USER RECORD. This routine checks
' the areacode, exchange, and last 4 numbers against numbers
' in the TRASHCAN.DAT file
'
GOSUB GET_PROCESS_PHONE_NUMBER
'
' If user has CID, and CIDNFO file exists, it will
' be displayed to the user. This file can be used
' to inform Caller ID users, to just hit "C" for
' continue, and the callback process will upgrade
' them automatically (if configured to auto-upgrade
' in .CFG entry #19), without having to perform an
' acutal callback.
'
IF (EXIST(PPEPATH() + "CIDNFO") && caller_id_info != "" && process_caller_id && upgrade_caller_id) DISPFILE PPEPATH() + "CIDNFO", GRAPH+SEC+LANG
'
' Show user what number will be used and ask them
' to: Continue, Re-enter, Exit the callback
'
NEWLINE
user_input = "C"
PRINTLN "@X0BPhone number used for Callback: @X1F", log_entry, "@X07"
NEWLINE
'
' If Caller-Id is being Used, Do not allow user to "Re-Enter"
' their phone number. Only allow them to Continue or Exit.
'
IF ((caller_id_info != "" && process_caller_id) || user_record_phone) THEN
main_prompt = "@X0EC@X0F)@X02ontinue callback process, @X0EE@X0F)@X02xit Callback@X0F"
INPUTSTR main_prompt, user_input, @X0B, 1, "CE", UPCASE+FIELDLEN+GUIDE+LFAFTER
ELSE
main_prompt = "@X0ER@X0F)@X02e-Enter Phone Number or @X0EC@X0F)@X02ontinue callback process, @X0EE@X0F)@X02xit Callback@X0F"
INPUTSTR main_prompt, user_input, @X0B, 1, "CER", UPCASE+FIELDLEN+GUIDE+LFAFTER
END IF
'
' See what the user entered
'
SELECT CASE (user_input)
'
' User choose to EXIT callback
'
CASE "E"
FPUTLN 7, "**-->> User aborted callback"
local_call = TRUE
GOTO EXIT_PROG
'
' User choose to RE-ENTER phone number
'
CASE "R"
FPUTLN 7, "#### User choose to RE-ENTER their phone number"
IF (improper_user_rec_phone) user_input = ""
CONTINUE
'
' Continue with callback
'
DEFAULT
BREAK
END SELECT
IF (user_input = "C") BREAK
END WHILE
NEWLINE
RETURN
'
' Retrieve CID information
'
:PROCESS_CALLER_ID_INFO
'
' Retrieve the caller id information
' Sample Caller ID information string:
'
' caller_id_info = "CID: DATE = 0111 TIME = 0015 NMBR = 3019464444"
'
' Some Phone Co. allow the user to have their NUMBER blocked when
' calling out. If so the number will come in as PRIVATE (see below)
' or possibly BLOCKED. Check with local phone co.
'
'caller_id_info = "CID: DATE = 0111 TIME = 0015 NMBR = 3019464372"
'caller_id_info = "3019464372 NAME=DAN_SHORE"
'
' Retrieve CID info
'
caller_id_info = TRIM(UPPER(CALLID())," ")
'
' Log RAW (not parsed yet) CID information being passed to PCB
'
FPUTLN 7, " RAW CID information: ", caller_id_info
'
' See if the variable "block_cid_string" is part of the CID string, and
' also check to see if SysOp wants to stop users who block CID info.
' If sysop is stopping any user who blocks CID info, then show
' the file NOBLOCK and exit from the PPE.
'
' NOTE: Some local phone companies allow you to stop any calls
' where a user is blocking caller id. This is stopped at
' the central office and never reaches your BBS. The user
' will receive a recording informing them of the inability
' to call the desired number with CID blocked. Again,
' check with your local phone company for this option.
'
IF (INSTR(caller_id_info, blocked_cid_string) && stop_blocked_cid_caller) THEN
DISPFILE PPEPATH() + "NOBLOCK", GRAPH+LANG+SEC
FPUTLN 7, "**-->> Blocked CID Info: User has CID Blocked - Exiting PPE"
DELAY 36
'
' Make sure we do not disconnect user
'
local_call = TRUE
GOTO EXIT_PROG
END IF
'
' See if cid_string_to_search is part of the CID string
'
' Find character position in string
'
hold = caller_id_info
IF (cid_string_to_search = "") THEN
int_count = 999
ELSE
int_count = INSTR(hold, cid_string_to_search)
END IF
IF (int_count) THEN
'
' No string to search for, just the number
'
IF (int_count = 999) int_count = 1
'
' Add length of number string to bypass string
'
' "NMBR =" (6 characters long) int_count = int_count + 6
'
int_count = int_count + LEN(cid_string_to_search)
'
' Get the phone number and trim spaces from both ends
'
hold = TRIM(MID(hold, int_count, LEN(hold) - (int_count-1))," ")
'
' Make sure we are only getting the phone number. Some CID
' strings have a name field after the phone number
'
IF (INSTR(hold, " ") != 0) hold = MID(hold, 1, INSTR(hold, " ")-1)
'
' Check to see if we have a phone number in the field. Sometimes
' a number will be "OUTOFAREA" and we do not want to use this as
' a callback number.
'
temp_real = TOREAL(hold)
IF (temp_real > 0) THEN
'
' See if the Phone number is in hex. If so convert it to
' an ASCII phone number.
'
IF (cid_use_hex) GOSUB CONVERT_HEX
'
ELSE
'
' No Phone number in CID field, so set to '0'
'
hold = "0"
'
END IF
'
' If no caller Id info (0), set it to blank
'
IF (hold = "0") THEN
caller_id_info = ""
ELSE
'
' Put CID information into CID variable
'
caller_id_info = hold
'
' If the CID information only has 7 digits (exchange and last 4)
' add the areacode found in configuration file to the beginning
'
IF (LEN(caller_id_info) = 7) caller_id_info = add_ac_to_cid + caller_id_info
'
END IF
'
ELSE
'
' If cid_string_to_search is not found, assume there is no
' caller id information to process.
'
caller_id_info = ""
'
END IF
RETURN
'
' Convert the HEX phone number string to an ASCII phone number.
'
' Code and information on HEX used WITH PERMISSION by Gary Meeker
'
' This code was originally from Gary's CIDPPE program. Thanks!
'
:CONVERT_HEX
'
' Initialize variables
'
count = 3
hold2 = ""
'
' Find length of HEX number
'
inp_length = S2I(MID(hold, count, 2), 16)
'
' Process until the entire "length" is read
'
WHILE (inp_length > 0) DO
count = count + 2
hold2 = hold2 + CHR(S2I(MID(hold, count, 2), 16))
DEC inp_length
END WHILE
'
' Put the converted number back into 'hold' variable
'
hold = hold2
RETURN
'
' Clear fields in CALLB display by overwriting info with spaces
'
:CLEAR_CALLB
ANSIPOS 26,9
SPRINT SPACE(45)
ANSIPOS 26,10
SPRINT SPACE(45)
ANSIPOS 26,11
SPRINT SPACE(45)
ANSIPOS 26,12
SPRINT SPACE(45)
ANSIPOS 26,13
SPRINT SPACE(45)
ANSIPOS 26,14
SPRINT SPACE(45)
ANSIPOS 2,18
SPRINT SPACE(60)
ANSIPOS 2,19
SPRINT SPACE(60)
ANSIPOS 26,9
RETURN
'
' Show how many seconds we have spent on current callback
'
:SHOW_TIMEOUT_COUNTDOWN
'
' See if enough time has elapsed to update the local callback scren
' with the time spent (in seconds) on the current callback
'
' If the time has not changed enough, do not update the screen.
'
IF (end_time - start_time >= current_timeout_value + 1 || current_timeout_value = 0) THEN
IF (current_timeout_value = 0) THEN
current_timeout_value = 1
ELSE
current_timeout_value = end_time - start_time
END IF
'
' Change color and update the local callback screen with the
' new timeout value for a callback
'
COLOR @X0F
ANSIPOS 66,7
SPRINT SPACE(3-LEN(current_timeout_value)), current_timeout_value
END IF
RETURN
'
' Check for SysOp interrupt - Carriage Return or Space Bar
'
' Carriage Return - Stops the Callback program
' Space Bar - Recycles the Callback program - Starts another call
'
:CHECK_SYSOP_KEY
hold = KINKEY()
IF (hold = 13 || hold = CHR(13)) THEN
'
' Flush the keyboard and modem buffers. Turn on Keyboard checking
' and carrier detect checking as the sysop has decided to abort
' the callback program by hitting ENTER
'
KBDCHKON
KBDFLUSH
MDMFLUSH
CDCHKON
'
' Change colors to write to screen
'
COLOR @X0F
ANSIPOS 3,18
SPRINT "**-->>"
COLOR @X0C
SPRINT " SysOp hit "
COLOR @X0F
SPRINT "ENTER "
COLOR @X0C
SPRINT "key to abort callback"
ANSIPOS 3,18
'
' Log the SysOp hit the ENTER key
'
FPUTLN 7, "**-->> SysOp hit ENTER key to abort callback"
DELAY 36
ANSIPOS 1,21
'
' Exit the program
'
GOTO EXIT_PROG
'
ELSE IF (hold = 32 || hold = CHR(32)) THEN
'
' Flush the keyboard and modem buffers
'
KBDFLUSH
MDMFLUSH
'
' Change colors to write to screen
'
COLOR @X0F
ANSIPOS 3,18
SPRINT "**-->>"
COLOR @X0A
SPRINT " SysOp hit "
COLOR @X0F
SPRINT "SPACE BAR "
COLOR @X0A
SPRINT "to recycle callback"
ANSIPOS 3,18
'
' Log the SysOp hit the space bar
'
FPUTLN 7, "**-->> SysOp hit SPACE BAR to recycle callback"
sysop_recycle = TRUE
COLOR @X0F
'
' Update the local callback screen for new call
'
current_timeout_value = 0
GOSUB SHOW_TIMEOUT_COUNTDOWN
DELAY 18
'
' Clear the callb screen fields display
'
GOSUB CLEAR_CALLB
'
END IF
RETURN
'
' Check the file BAD_NUM.LST for a matching phone number. If a match
' is found, display the file BADNUM to use and exit the PPE.
'
' NOTE: The format of BADNUM is one phone number per line. Comments
' are allowed from the 11th character to the end of the line.
'
' Example of entries in BAD_NUM.LST
'
' 3019993456 - Number used by banned user
' 3015552234 - SysOps voice number
' 301555???? - Block all calls to areacode 301 with exchange 555
' *041???????????? - Block all International calls to Country Code 041
'
' Any text from column 26 to the end of the line
' can be used for commenting the file.
'
' Wildcards can also be used to help BLOCK certain numbers. See the
' file CB.DOC for proper usage and entry formats
'
'
:CHECK_BAD_NUMBER
'
' Initialize variables
'
found1 = FALSE
int_count = 0
'
' Open file in read only mode
'
FOPEN 2, PPEPATH() + "BAD-NUM.LST", O_RD, S_DN
FPUTLN 7, " Checking Number against: BAD-NUM.LST"
WHILE (1) DO
FGET 2, hold2
IF (FERR(2)) BREAK
'
' See if the line is a comment
'
IF (LEFT(hold2,1) = "#" || LEFT(hold2,1) = "'") CONTINUE
'
' If US calling plan and we read an International entry,
' read the next line
'
IF (cp_required = 1 && LEFT(hold2,1) = "*") CONTINUE
'
' Retrieve first 25 characters of the line AND TRIM OFF spaces
'
hold2 = RTRIM(MID(hold2, 1, 25)," ")
'
' Check to see if we are using wildcards in the BAD-NUM.LST entry
'
IF (cp_required = 1) THEN
'
' Find position of wildcard character in line. INSTR will
' report back the first "?" is finds on the line
'
int_count = INSTR(hold2, "?")
SELECT CASE (int_count)
CASE 1
IF (MID(hold2, 4, 7) = exchange + last_4_nums) found1 = TRUE
CASE 4
IF (MID(hold2, 1, 3) = area_code && MID(hold2, 7, 4) = last_4_nums) found1 = TRUE
CASE 7
IF (MID(hold2, 1, 6) = area_code + exchange) found1 = TRUE
DEFAULT
IF (hold2 = phone_number) found1 = TRUE
END SELECT
ELSE IF (cp_required = 2) THEN
'
' Strip leading "*" from International entry
'
hold2 = MID(hold2, 2, 24)
'
' Find position of wildcard character in line. INSTR will
' report back the first "?" is finds on the line
'
int_count = INSTR(hold2, "?")
SELECT CASE (int_count)
CASE 1
IF (RTRIM(MID(hold2, 4, 12)," ") = exchange_code + last_nums) found1 = TRUE
CASE 4
IF (RTRIM(MID(hold2, 1, 3)," ") = exchange_code && MID(hold2, 8, 8) = last_nums) found1 = TRUE
CASE 8
IF (RTRIM(MID(hold2, 1, 7)," ") = country_code + exchange_code) found1 = TRUE
DEFAULT
IF (hold2 = phone_number) found1 = TRUE
END SELECT
END IF
'
' If we match a phone number, display file BADNUM
' and exit out of the program
'
IF (found1) THEN
DISPFILE PPEPATH() + "BADNUM", GRAPH+LANG+SEC
FPUTLN 7, "**-->> Match Found in: BAD-NUM.LST"
NEWLINE
WAIT
GOTO EXIT_PROG
END IF
END WHILE
'
' If we get to here, there was no match found
'
FPUTLN 7, " No match found in: BAD-NUM.LST"
FCLOSE 2
RETURN
'
' Clean up Data and Voice user record phone numbers
'
:PREPARE_DATA_VOICE_NUMBERS
'
' Clean up Data Phone Number from user record
'
d_phone_number = U_BDPHONE
hold = d_phone_number
GOSUB CLEAN_UP_NUMBER
d_phone_number = hold
'
' Clean up Voice phone number from user record
'
h_phone_number = U_HVPHONE
hold = h_phone_number
GOSUB CLEAN_UP_NUMBER
h_phone_number = hold
RETURN
'
' Subroutine to determine where to post callback information
' in user record COMMENT or NOTES
'
:POST_COMMENT_NOTES
'
' Put phone number into HOLD2 variable depending on calling plan
'
IF (cp_required = 1) THEN
hold2 = area_code + "-" + exchange + "-" + last_4_nums
ELSE
hold2 = phone_number
END IF
'
' See which option was chosen for posting
'
SELECT CASE (post_cbinfo_user_record)
'
' Post to COMMENT #1 or COMMENT #2 depending on which field
' has no information in it already
'
CASE "COMMENT"
'
' If COMMENT1 is blank (or all spaces), write info to it
'
IF (U_CMNT1 = "" || U_CMNT1 = SPACE(LEN(U_CMNT1))) THEN
U_CMNT1 = STRING(DATE()) + " " + STRING(TIME()) + " " + hold2
'
' If COMMENT2 is blank (or all spaces), write info to it
'
ELSE IF (U_CMNT2 = "" || U_CMNT2 = SPACE(LEN(U_CMNT2))) THEN
U_CMNT2 = STRING(DATE()) + " " + STRING(TIME()) + " " + hold2
'
' Both COMMENT fields are used, inform SysOp in LOG file
'
ELSE
FPUTLN 7, "**-->> Both Comment Fields Used - Unable to write info"
END IF
'
' Post directly to COMMENT #1 irrelevant of the information
' that might be already there.
'
CASE "COMMENT1"
U_CMNT1 = STRING(DATE()) + " " + STRING(TIME()) + " " + hold2
'
' Post directly to COMMENT #2 irrelevant of the information
' that might be already there.
'
CASE "COMMENT2"
U_CMNT2 = STRING(DATE()) + " " + STRING(TIME()) + " " + hold2
'
' Post to the NOTES field(s) only if the PSA is installed.
' Check each field to make sure we have room to post the
' information. If all fields are full, then the information
' will not get posted to the NOTES fields
'
' The NOTES fields consist of 5 lines consisting of a maximum
' of 60 characters each
'
CASE "NOTES"
'
' Check to see if the NOTES PSA is installed
'
IF (PSA(6)) THEN
'
' User NOTES is made up of 5 lines, with each line having a
' maximum of 60 characters. If a line is less than 30 chars
' long, add the callback info to the end of the line. Else,
' find the first blank line to write callback info to
'
IF (LEN(U_NOTES(0)) < 30 || U_NOTES(0) = SPACE(LEN(U_NOTES(0)))) THEN
U_NOTES(0) = TRIM(U_NOTES(0)," ") + STRING(DATE()) + " " + STRING(TIME()) + " " + hold2
ELSE IF (LEN(U_NOTES(1)) < 30 || U_NOTES(1) = SPACE(LEN(U_NOTES(1)))) THEN
U_NOTES(1) = TRIM(U_NOTES(1)," ") + STRING(DATE()) + " " + STRING(TIME()) + " " + hold2
ELSE IF (LEN(U_NOTES(2)) < 30 || U_NOTES(2) = SPACE(LEN(U_NOTES(2)))) THEN
U_NOTES(2) = TRIM(U_NOTES(2)," ") + STRING(DATE()) + " " + STRING(TIME()) + " " + hold2
ELSE IF (LEN(U_NOTES(3)) < 30 || U_NOTES(3) = SPACE(LEN(U_NOTES(3)))) THEN
U_NOTES(3) = TRIM(U_NOTES(3)," ") + STRING(DATE()) + " " + STRING(TIME()) + " " + hold2
ELSE IF (LEN(U_NOTES(4)) < 30 || U_NOTES(4) = SPACE(LEN(U_NOTES(4)))) THEN
U_NOTES(4) = TRIM(U_NOTES(4)," ") + STRING(DATE()) + " " + STRING(TIME()) + " " + hold2
'
' All NOTES fields are used, inform SysOp in LOG file
'
ELSE
FPUTLN 7, "**-->> All NOTES Fields Used - Unable to write info"
END IF
ELSE
FPUTLN 7, "**-->> NOTES PSA is not installed - See PCB Manual for Installation"
END IF
END SELECT
RETURN